package Cinema.Tests;

import static org.junit.Assert.*;

import java.util.Date;
import java.util.List;

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import Utils.XmlParseHelper;

import Auxiliary.PaymentDetails;
import Cinema.CinemaEntities.IShow;
import Cinema.CinemaEntities.Movie;
import Cinema.CinemaEntities.Order;
import Cinema.CinemaEntities.Theater;
import Exceptions.CinemaException;
import Exceptions.DataAccessException;
import Exceptions.IllegalSeatsFormat;
import Exceptions.OperationCanceledException;
import Exceptions.OrderFailed;
import Exceptions.PaymentFailed;
import Exceptions.SeatAlreadyFree;
import Exceptions.ShowExpierd;
import Exceptions.WrongXMLElement;



public class OrderTest implements IXmlParsableTest {

	
	TestOrder order;
	Date showDate;
	PaymentDetails paymentDetails;
	int numberOfAdults;
	int numberOfChilds;
	IShow testShow;
	String movieName;
	String movieGenre;
	
	@SuppressWarnings("deprecation")
	@Before
	public void InitTest()
	{
		paymentDetails = new PaymentDetails(12345678,"Visa",new Date(3221), 323);
		numberOfAdults = 5;
		numberOfChilds = 5;
		movieName = "piter pen";
		showDate = new Date();
		showDate.setYear(2012);
		showDate.setMonth(1);
		showDate.setDate(31);
		showDate.setHours(22);
		showDate.setMinutes(0);
		showDate.setSeconds(0);
		testShow = new TestShow();
		try {
			order = new TestOrder(testShow,5,5,"lalala@gmail.com");
		} catch (CinemaException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Test payment Details getter
	 */
	@Test
	public void testGetPaymentDetails() {
		PaymentDetails res = order.getPaymentDetails();
		assertSame(res, paymentDetails);
	}

	/**
	 * Test get show getter
	 */
	@Test
	public void testGetShow() {
		assertSame(order.getShow(), testShow);
	}

	/**
	 * Test Get num of seats function
	 */
	@Test
	public void testGetNumOfSeats() {
		assertEquals(order.getNumOfSeats(), numberOfAdults + numberOfChilds);
	}

	/**
	 * Test get movie getter
	 */
	@Test
	public void testGetMovieName() {
		assertEquals(movieName, order.getMovieName());
	}

	/**
	 * Test get show date getter
	 */
	@Test
	public void testGetShowDate() {
		assertEquals(showDate, order.getShowDate());
	}

	/**
	 * Test cancel order function
	 */
	@Test (expected = ShowExpierd.class)
	public void testCancelOrder() throws ShowExpierd, PaymentFailed {
		showDate = new Date(System.currentTimeMillis() - 1);
		testShow = new TestShow();
		try {
			order = new TestOrder(testShow,5,5,"lalala@gmail.com");
		} catch (CinemaException e) {
			e.printStackTrace();
		}
		
		order.CancelOrder();
	}
	
	/**
	 * Test check equals getter
	 */
	@SuppressWarnings("deprecation")
	@Test
	public void testCheckEquals() {
		paymentDetails = new PaymentDetails(12345678,"Visa",new Date(3221), 323);
		showDate = new Date();
		showDate.setYear(2012);
		showDate.setMonth(1);
		showDate.setDate(31);
		showDate.setHours(22);
		showDate.setMinutes(0);
		showDate.setSeconds(0);
		IShow sameTestShow = new TestShow();
		Order sameOrder = null;
		try {
			sameOrder = new TestOrder(sameTestShow,numberOfAdults,numberOfChilds,"lalala@gmail.com");
		} catch (CinemaException e) {
			assertTrue(false);
		}
		assertTrue(sameOrder.checkEquals(order));
	}

	/**
	 * Test get xml function
	 */
	@Test
	@Override
	public void test_getXml() throws DataAccessException, OperationCanceledException, OrderFailed, PaymentFailed {
		
		//payment details
		long cardNumber = 1234123412341234L;
		String cardName = "Alaa Shitot";
		Date validDate = new Date(123456789);
		int CSC = 123;
		paymentDetails = new PaymentDetails(cardNumber, cardName, validDate, CSC);
		
		//tickets prisees
		numberOfAdults = 10;
		numberOfChilds = 7;
		
		TestOrder testOrder = null;
		testOrder = new TestOrder(new TestShow(), 2, 3, "alaa@gmail.com");
		testOrder.setShowId(7979);
		
		//create test doc
		Document testDoc = XmlParseHelper.createNewDocument();
		testDoc.appendChild(testOrder.getXml(testDoc));
		
		//create control doc
		Document controlDoc = XmlParseHelper.getDocumentFromFile(".\\tests\\testXml\\OrderTest.xml");
		
		//comparing
		Diff diff = new Diff(controlDoc, testDoc);
		DetailedDiff detailedDiff = new DetailedDiff(diff);
		
		//for debugging - itereate over differences
		@SuppressWarnings("unchecked")
		List<Difference> difList = detailedDiff.getAllDifferences();
		for (Difference difference : difList) {
			String discription = difference.getDescription();
			discription.toString();
		}
		
		assertTrue(detailedDiff.similar());
		
	}

	/**
	 * Test init from xml
	 */
	@Test
	@Override
	public void test_initFromXml() throws DataAccessException {
		
		TestOrder controlOrder = new TestOrder();
		
		//payment details
		long cardNumber = 4321432143214321L;
		String cardName = "Ofir Haviv";
		Date validDate = new Date(222222);
		int CSC = 111;
		paymentDetails = new PaymentDetails(cardNumber, cardName, validDate, CSC);
		
		//building control object
		controlOrder.setPayment(paymentDetails);
		controlOrder.setPaid(79);
		Integer[] seats = new Integer[4];
		seats[0] = 7;
		seats[1] = 10;
		seats[2] = 11;
		seats[3] = 12;
		controlOrder.setSeats(seats);
		controlOrder.setShowId(797979);
		
		Document testDocument = XmlParseHelper.getDocumentFromFile(".\\tests\\testXml\\OrderTest2.xml");
		TestOrder testOrder = new TestOrder(testDocument.getDocumentElement());
		
		boolean eq = controlOrder.checkEquals(testOrder);
		assertTrue(eq);
				
	}

	
	private class TestOrder extends Order {
		
		public TestOrder(IShow show, int numberOfAdults, int numberOfChilds, String eMail) throws OperationCanceledException, OrderFailed, PaymentFailed{
			super(show,numberOfAdults, numberOfChilds, eMail);
		}
		
		public TestOrder() {
		}
		
		public TestOrder(Element element) throws WrongXMLElement{
			super(element);
		}
		
		public void  setShowId(long id){
			showID = id;
		}
		
		public void setSeats(Integer[] seats){
			this.seats = seats;
		}
		
		public void setPaid(int paid){
			this.paid = paid;
		}
		
		public void setPayment(PaymentDetails payment){
			this.creditDetails = payment;
		}
		
		@Override
		protected void SendTickets(IShow show, String eMail){
		}
		
		@Override
		protected PaymentDetails GetPaymentDetails(){
			return paymentDetails;
		}
		
		@Override
		protected Boolean PayForTicket(PaymentDetails paymentDetails, int sum){
			return true;
		}
		
		@Override
		protected Boolean RefoundTickets(double sum){
			return true;
		}
	}
	
	/**
	 * stub for Show class
	 */
	private class TestShow implements IShow{

		@Override
		public String getMovieGenre() {
			return movieGenre;
		}
		 
		@Override
		public void saveMovie(Movie movie) {
		}

		@Override
		public Movie getMovie() {
			return null;
		}

		@Override
		public Theater getTheater() {
			return null;
		}

		@Override
		public String getMovieName() {
			return movieName;
		}

		@Override
		public Date getShowDate() {
			return showDate;
		}

		@Override
		public void freeSeats(Integer[] seats) throws SeatAlreadyFree,
				IllegalSeatsFormat {
			
		}

		@Override
		public Integer[] OrderPlaces(int numberOfSeats) {
			Integer[] res = new Integer[numberOfSeats + 1];
			res[0] = 4;
			for (int i = 0; i < numberOfSeats; i++)
				res[i+1] = i + 5;
			return res;
		}

		@Override
		public Boolean checkOrderPossibility(int numberOfSeats) {
			return true;
		}

		@Override
		public int getAdultTicketPrice() {
			return numberOfAdults;
		}

		@Override
		public int getChildTicketPrice() {
			return numberOfChilds;
		}

		@Override
		public long getId() {
			return 0;
		}
		
	}
}
